package com.longtop.sp.mapdao.meta;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.SqlProvider;
import org.springframework.jdbc.core.StatementCallback;
import org.springframework.jdbc.support.JdbcUtils;

/**
 * 缓存ResultSetMetaData对象
 * 
 * @author leexh
 * @version $Revision: 1.1 $
 */

public class TableMetaData {
	private static Log log = LogFactory.getLog(TableMetaData.class);
	private ColumnMetaData data[] = null;
	private int columnCount;

	public TableMetaData(JdbcTemplate jt, String tableName) throws SQLException {
		final String sql = "SELECT * FROM " + tableName + " WHERE 1=0";
		if (log.isDebugEnabled())
			log.debug("获取表" + tableName + "的ResultSetMetaData的sql=" + sql);
		class QueryStatementCallback implements StatementCallback, SqlProvider {
			public Object doInStatement(Statement stmt) throws SQLException {
				ResultSet rs = null;
				try {
					rs = stmt.executeQuery(sql);
					setResultSet(rs);
					return null;
				} finally {
					JdbcUtils.closeResultSet(rs);
				}
			}

			public String getSql() {
				return sql;
			}

		}
		jt.execute(new QueryStatementCallback());
	}

	public TableMetaData(ResultSet rs) throws SQLException {
		setResultSet(rs);
	}

	private void setResultSet(ResultSet rs) throws SQLException {
		ResultSetMetaData rsmt = rs.getMetaData();
		columnCount = rsmt.getColumnCount();
		data = new ColumnMetaData[columnCount]; // ResultSetMetaData是从1开始的，数组是从0开始的
		for (int i = 1; i <= columnCount; i++) {
			ColumnMetaData meta = new ColumnMetaData();
			meta.setName(rsmt.getColumnName(i)); // 应该是大写
			// rsmt.isNullable(i)有3个返回值，对于 columnNullableUnknown
			// 我从来没有遇到过，所以，认为只有2个返回值。
			meta.setNullable(rsmt.isNullable(i) == ResultSetMetaData.columnNullable);
			int iType = rsmt.getColumnType(i);
			meta.setType(iType);
			int precision;
			if (iType == Types.BLOB || iType == Types.CLOB
					|| iType == Types.LONGVARBINARY
					|| iType == Types.LONGVARCHAR) {
				precision = Integer.MAX_VALUE;
			} else {
				precision = rsmt.getColumnDisplaySize(i); // rsmt.getPrecision(i)在Sybase的jdbc应该是取数值精度，如果有字符类型的会出错。
			}
			meta.setPrecision(precision);
			meta.setScale(rsmt.getScale(i));
			meta.setTypeName(rsmt.getColumnTypeName(i));
			data[i - 1] = meta;
		}
	}

	public ColumnMetaData getColumnMetaData(int i) {
		return data[i - 1];
	}

	public ColumnMetaData getColumnMetaData(String columnName) {
		if (columnName == null) {
			return null;
		}
		for (int i = 0; i < data.length; i++) {
			if (data[i].getName().equalsIgnoreCase(columnName)) {
				return data[i];
			}
		}
		return null;
	}

	public int getColumnCount() {
		return this.columnCount;
	}

	public String getName(int i) {
		return getColumnMetaData(i).getName();
	}

	public int getType(int i) {
		return getColumnMetaData(i).getType();
	}

	public String getTypeName(int i) {
		return getColumnMetaData(i).getTypeName();
	}

	public int getPrecision(int i) {
		return getColumnMetaData(i).getPrecision();
	}

	public int getScale(int i) {
		return getColumnMetaData(i).getScale();
	}

	public boolean isNullable(int i) {
		return getColumnMetaData(i).isNullable();
	}
}